package com.leyou.item.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fasterxml.jackson.core.type.TypeReference;
import com.leyou.common.dto.PageDTO;
import com.leyou.common.exception.LyException;
import com.leyou.common.utils.JsonUtils;
import com.leyou.item.dto.SkuDTO;
import com.leyou.item.dto.SpecParamDTO;
import com.leyou.item.dto.SpuDTO;
import com.leyou.item.dto.SpuDetailDTO;
import com.leyou.item.entity.*;
import com.leyou.item.mapper.SpuMapper;
import com.leyou.item.service.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;


@Service
public class SpuServiceImpl extends ServiceImpl<SpuMapper, Spu> implements SpuService {
    @Autowired
    private BrandService brandService;
    @Autowired
    private CategoryService categoryService;
    @Autowired
    private SkuService skuService;
    @Autowired
    private SpuDetailService detailService;
    @Autowired
    private SpecParamService specParamService;

    @Override
    public PageDTO<SpuDTO> querySpuByPage(Integer page, Integer rows, Boolean saleable, Long categoryId, Long brandId, Long id) {
        int current = Math.max(page, 1);
        int size = Math.max(rows, 5);


//        IPage<Spu> ipage=new Page<>(page,rows);
//        page(ipage,new QueryWrapper<Spu>()
//                .eq(null!=id,"id",id)
//                .eq(null!=categoryId,"cid3",categoryId)
//                .eq(null!=brandId,"brand_id",brandId)
//                .eq(null!=saleable,"saleable",saleable)
//        );
//        List<SpuDTO> spuDTOS = SpuDTO.convertEntityList(ipage.getRecords());

        // 2.准备查询条件， SELECT * FROM tb_spu WHERE saleable = ? AND category_id = ? AND brand_id = ? AND id = ?
        Page<Spu> result = query()
                .eq(saleable != null, "saleable", saleable)
                .eq(categoryId != null, "cid3", categoryId)
                .eq(brandId != null, "brand_id", brandId)
                .eq(id != null, "id", id)
                // 3.准备分页条件 LIMIT ?, ?
                .page(new Page<>(current, size));

        // 4.解析查询结果
        long total = result.getTotal();
        long pages = result.getPages();
        List<Spu> list = result.getRecords();

        // 5.转换DTO
        List<SpuDTO> dtoList = SpuDTO.convertEntityList(list);
        for (SpuDTO spuDTO : dtoList) {
            // 查询spu的分类和品牌的名称
            handleCategoryAndBrandName(spuDTO);
        }

        // 6.封装分页结果并返回
        return new PageDTO<>(total, pages, dtoList);
    }


    @Override
    @Transactional
    public void saveGoods(SpuDTO spuDTO) {
        Spu spu = spuDTO.toEntity(Spu.class);
        save(spu);
        SpuDetail spuDetail = spuDTO.getSpuDetail().toEntity(SpuDetail.class);
        spuDetail.setSpuId(spu.getId());
        this.detailService.save(spuDetail);
        List<Sku> skus = spuDTO.getSkus().stream().map(skuDTO -> {
            Sku sku = skuDTO.toEntity(Sku.class);
            sku.setSpuId(spu.getId());
            return sku;
        }).collect(Collectors.toList());
        this.skuService.saveBatch(skus);
//        // 1.新增Spu
//        Spu spu = spuDTO.toEntity(Spu.class);
//        spu.setSaleable(false);
//        boolean success = save(spu);
//        if (!success) {
//            throw new LyException(500, "新增商品失败");
//        }
//        // 2.新增SpuDetail
//        SpuDetail spuDetail = spuDTO.getSpuDetail().toEntity(SpuDetail.class);
//        spuDetail.setSpuId(spu.getId());
//        success = detailService.save(spuDetail);
//        if (!success) {
//            throw new LyException(500, "新增商品详情失败");
//        }
//        // 3.新增Sku
//        List<Sku> list = spuDTO.getSkus().stream().map(skuDTO -> {
//            Sku sku = skuDTO.toEntity(Sku.class);
//            sku.setSaleable(false);
//            sku.setSpuId(spu.getId());
//            return sku;
//        }).collect(Collectors.toList());
//        // 批量新增
//        skuService.saveBatch(list);
    }

    @Override
    @Transactional
    public void updateSaleable(Long id, Boolean saleable) {
        Spu spu = new Spu();
        spu.setId(id);
        spu.setSaleable(saleable);
        updateById(spu);

        Sku sku = new Sku();
        sku.setSaleable(saleable);
        this.skuService.update(sku,new QueryWrapper<Sku>()
                .eq("spu_id",id)
                .eq("saleable",!saleable));


        //        // 1.更新SPU
//        Spu spu = new Spu();
//        spu.setId(id);
//        spu.setSaleable(saleable);
//        boolean success = updateById(spu);
//        if (!success) {
//            throw new LyException(500, "更新失败");
//        }
//        // 2.更新sku
//        success = skuService.update().eq("spu_id", id).set("saleable", saleable).update();
//        if (!success) {
//            throw new LyException(500, "更新失败");
//        }
    }

    @Override
    public SpuDTO queryGoodsById(Long id) {
        Spu spu = getById(id);
        if (spu == null) {
            throw new LyException(400, "商品id不存在！");
        }
        // 1.2.转换DTO
        SpuDTO spuDTO = new SpuDTO(spu);

        // 2.查询spuDetail
        SpuDetail detail = detailService.getById(id);
        if (detail == null) {
            throw new LyException(400, "商品id不存在！");
        }
        spuDTO.setSpuDetail(new SpuDetailDTO(detail));

        // 3.查询sku
        List<Sku> list = skuService.query().eq("spu_id", id).list();
        if (CollectionUtils.isEmpty(list)) {
            throw new LyException(400, "商品id不存在！");
        }
        spuDTO.setSkus(SkuDTO.convertEntityList(list));

        // 4.准备商品分类和品牌名称
        handleCategoryAndBrandName(spuDTO);

        return spuDTO;
    }

    @Override
    @Transactional
    public void updateGoods(SpuDTO spuDTO) {
        if (null != spuDTO.getId()) {
            updateById(spuDTO.toEntity(Spu.class));
        }
        if (null != spuDTO.getSpuDetail()) {
            this.detailService.updateById(spuDTO.getSpuDetail().toEntity(SpuDetail.class));
        }
        if (null != spuDTO.getSkus() && 0 != spuDTO.getSkus().size()) {
            List<Sku> skus = spuDTO.getSkus().stream().map(skuDTO -> {
                Sku sku = skuDTO.toEntity(Sku.class);
                return sku;
            }).collect(Collectors.toList());
            Map<Boolean, List<Sku>> map = skus.stream()
                    .collect(Collectors.groupingBy(sku -> sku.getSaleable() == null));
            this.skuService.saveOrUpdateBatch(map.get(true));
            this.skuService.removeByIds(map.get(false).stream().map(Sku::getId).collect(Collectors.toList()));

        }

//        Long spuId = spuDTO.getId();
//        if(spuId != null){
//            // 1.2.spu需要修改，更新spu, 转换dto
//            Spu spu = spuDTO.toEntity(Spu.class);
//            // 1.3.更新
//            boolean success = updateById(spu);
//            if(!success){
//                // 更新失败，抛出异常
//                throw new LyException(500, "更新商品失败！");
//            }
//        }
//        // 2.修改spuDetail
//        SpuDetailDTO detailDTO = spuDTO.getSpuDetail();
//        // 2.1.判断是否为null
//        if (detailDTO != null && detailDTO.getSpuId() != null) {
//            // 2.2.spuDetail存在，需要修改，转换DTO
//            SpuDetail detail = detailDTO.toEntity(SpuDetail.class);
//            boolean success = detailService.updateById(detail);
//            if(!success){
//                // 更新失败，抛出异常
//                throw new LyException(500, "更新商品失败！");
//            }
//        }
//        // 3.修改sku
//        List<SkuDTO> dtoList = spuDTO.getSkus();
//        // 3.1.判断是否包含sku
//        if(CollectionUtils.isEmpty(dtoList)){
//            return;
//        }
//        // 3.2.转换DTO，并将sku根据saleable是否为null来分组。null，是新增或修改，不是null是删除
//        Map<Boolean, List<Sku>> map = dtoList.stream()
//                .map(skuDTO -> skuDTO.toEntity(Sku.class))
//                .collect(Collectors.groupingBy(sku -> sku.getSaleable() == null));
//
//        // 3.3.获取要新增或修改的sku
//        List<Sku> insertOrUpdateList = map.get(true);
//        // 如果不为空，则修改或新增
//        if(!CollectionUtils.isEmpty(insertOrUpdateList)) {
//            skuService.saveOrUpdateBatch(insertOrUpdateList);
//        }
//
//        // 3.4.获取要删除的sku
//        List<Sku> deleteSkuList = map.get(false);
//        if(!CollectionUtils.isEmpty(deleteSkuList)){
//            // 存在要删除的sku
//            List<Long> idList = deleteSkuList.stream().map(Sku::getId).collect(Collectors.toList());
//            // 删除
//            skuService.removeByIds(idList);
//        }
    }

    @Override
    public List<SpecParamDTO> querySpecValues(Long id, Boolean searching) {
        Long categoryId = this.getById(id).getCid3();
        List<SpecParamDTO> specParamDTOS=SpecParamDTO.convertEntityList(this.specParamService .query()
                .eq("categoryId",categoryId)
                .eq(null!=searching,"searchig",searching).list());

        Map<Long,Object> paramMap=JsonUtils.nativeRead(this.detailService.getById(id).getSpecification(), new TypeReference<Map<Long, Object>>() {
        });

        specParamDTOS.forEach(specParamDTO -> {
            specParamDTO.setValue(paramMap.get(specParamDTO.getId()));
        });
        return specParamDTOS;
    }

    private void handleCategoryAndBrandName(SpuDTO spuDTO) {
        // 根据品牌id查询品牌名称
        Brand brand = brandService.getById(spuDTO.getBrandId());
        if (brand != null) {
            spuDTO.setBrandName(brand.getName());
        }
        // 根据三级分类id查询分类集合
        List<Category> categories = categoryService.listByIds(spuDTO.getCategoryIds());
        if (!CollectionUtils.isEmpty(categories)) {
            // 取出分类的名称，拼接起来
            String names = categories.stream().map(Category::getName).collect(Collectors.joining("/"));
            spuDTO.setCategoryName(names);
        }
    }
}
